package com.zenika.zenbinding.client.widget;

import java.util.List;

import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.zenika.zenbinding.client.ZenBinder;
import com.zenika.zenbinding.client.converter.Converter;
import com.zenika.zenbinding.client.converter.EnumConverter;
import com.zenika.zenbinding.client.converter.Radio2BooleanConverter;
import com.zenika.zenbinding.client.handler.ListBindingHandler;
import com.zenika.zenbinding.client.model.BusinessObject;
import com.zenika.zenbinding.client.model.ListModel;
import com.zenika.zenbinding.client.model.ValueModel;
import com.zenika.zenbinding.client.model.ZenEnum;

public class VerticalUserFormPanel extends Grid {

	private final static int DEFAULT_COLUMNS_PER_INPUT = 2;

	protected int nbColumnsPerInputColumn;
	protected int currentInputRow;

	/**
	 * FIXME provide a default implementation with two columns with a special build() method that splits the fields
	 * between the two columns automatically. FIXME also create an implementation using FlexTable
	 */
	public VerticalUserFormPanel(int nbInputRows) {
		this(nbInputRows, DEFAULT_COLUMNS_PER_INPUT);
	}

	protected VerticalUserFormPanel(int nbInputRows, int nbColumnsPerInputColumn) {
		super(nbInputRows, nbColumnsPerInputColumn);
		// FIXME DEBUG
		this.setBorderWidth(1);
		this.currentInputRow = 0;
		this.nbColumnsPerInputColumn = nbColumnsPerInputColumn;
	}

	public ValueModel addTextBox(BusinessObject object, String property, String label) {
		Label associatedLabel = new Label(label);
		TextBox textBox = new TextBox();

		ValueModel valueModel = ZenBinder.bindValue(textBox, object, property);
		this.addEntryToPanel(associatedLabel, textBox);
		return valueModel;
	}

	public ValueModel addTextArea(BusinessObject object, String property, String label) {
		Label associatedLabel = new Label(label);

		TextArea textArea = new TextArea();
		ValueModel valueModel = ZenBinder.bindValue(textArea, object, property);
		this.addEntryToPanel(associatedLabel, textArea);
		return valueModel;
	}

	public ValueModel addCheckBox(BusinessObject object, String property, String label) {
		Label associatedLabel = new Label(label);
		CheckBox checkBox = new CheckBox();

		ValueModel valueModel = ZenBinder.bindValue(checkBox, object, property);
		this.addEntryToPanel(associatedLabel, checkBox);
		return valueModel;
	}

	public ListModel addRadioGroup(BusinessObject businessObject, String property, List businessObjects,
			String propertyInList, String label, boolean isVertical) {

		BusinessObject[] businessObjectsArray = (BusinessObject[]) businessObjects
				.toArray(new BusinessObject[businessObjects.size()]);
		return this.addRadioGroup(businessObject, property, businessObjectsArray, label, isVertical);
	}

	public ListModel addRadioGroup(BusinessObject businessObject, String property, BusinessObject[] businessObjects,
			String propertyInArray, String label, boolean isVertical) {

		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		RadioGroup radioGroup = new RadioGroup(isVertical);

		ListBindingHandler handler = ZenBinder.createListBindingHandler(radioGroup, businessObjects, propertyInArray);
		return this.addRadioGroup(businessObject, property, handler, radioGroup, associatedLabel);
	}

	public ListModel addRadioGroup(BusinessObject businessObject, String property, List choices, String label,
			boolean isVertical) {

		Object[] choicesArray = choices.toArray(new Object[choices.size()]);
		return this.addRadioGroup(businessObject, property, choicesArray, label, isVertical);
	}

	public ListModel addRadioGroup(BusinessObject businessObject, String property, Object[] choices, String label,
			boolean isVertical) {

		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		RadioGroup radioGroup = new RadioGroup(isVertical);

		ListBindingHandler handler = ZenBinder.createListBindingHandler(radioGroup, choices);
		return this.addRadioGroup(businessObject, property, handler, radioGroup, associatedLabel);
	}

	public ListModel addBooleanRadioGroup(BusinessObject businessObject, String property, String[] choices,
			String label, boolean isVertical) {

		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		RadioGroup radioGroup = new RadioGroup(isVertical);

		ListBindingHandler handler = ZenBinder.createListBindingHandler(radioGroup, choices);
		return this.addRadioGroup(businessObject, property, handler, radioGroup, associatedLabel,
				new Radio2BooleanConverter(choices));
	}

	private ListModel addRadioGroup(BusinessObject businessObject, String property, ListBindingHandler handler,
			RadioGroup radioGroup, Label associatedLabel) {
		return this.addRadioGroup(businessObject, property, handler, radioGroup, associatedLabel, null);
	}

	private ListModel addRadioGroup(BusinessObject businessObject, String property, ListBindingHandler handler,
			RadioGroup radioGroup, Label associatedLabel, Converter converter) {

		ListModel listModel = ZenBinder.bindList(handler, businessObject, property, converter);

		this.addEntryToPanel(associatedLabel, radioGroup);
		return listModel;
	}

	public ListModel addListBox(BusinessObject businessObject, String property, BusinessObject[] businessObjects,
			String propertyInArray, String label) {
		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		ListBox listBox = new ListBox();

		ListModel listModel = ZenBinder
				.bindListBox(listBox, businessObject, property, businessObjects, propertyInArray);

		this.addEntryToPanel(associatedLabel, listBox);

		return listModel;
	}

	public ListModel addListBox(BusinessObject businessObject, String property, Object[] choices, String label) {
		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		ListBox listBox = new ListBox();

		ListModel listModel = ZenBinder.bindListBox(listBox, businessObject, property, choices);

		this.addEntryToPanel(associatedLabel, listBox);

		return listModel;
	}

	public ListModel addListBox(BusinessObject businessObject, String property, List choices, String label) {

		Object[] choicesArray = (Object[]) choices.toArray(new Object[choices.size()]);

		return this.addListBox(businessObject, property, choicesArray, label);
	}

	public ListModel addEnumListBox(BusinessObject businessObject, String property, ZenEnum[] choices, String label) {

		Label associatedLabel = null;
		if (label != null)
			associatedLabel = new Label(label);
		ListBox listBox = new ListBox();

		ListBindingHandler handler = ZenBinder.createListBindingHandler(listBox, choices);
		ListModel listModel = ZenBinder.bindList(handler, businessObject, property, new EnumConverter(choices));

		this.addEntryToPanel(associatedLabel, listBox);

		return listModel;
	}

	public ListModel addListBox(BusinessObject businessObject, String property, List businessObjects,
			String propertyInList, String label) {

		BusinessObject[] businessObjectArray = (BusinessObject[]) businessObjects
				.toArray(new BusinessObject[businessObjects.size()]);

		return this.addListBox(businessObject, property, businessObjectArray, propertyInList, label);
	}

	private void addEntryToPanel(Label label, Widget widget) {
		// add the label
		int column = 0;
		System.out.println("(" + this.currentInputRow + "," + column + ") = " + label);
		if (label != null)
			this.setWidget(this.currentInputRow, column, label);

		// add the input widget
		column++;
		System.out.println("(" + this.currentInputRow + "," + column + ") = " + widget);
		this.setWidget(this.currentInputRow, column, widget);

		// go to the next row
		this.currentInputRow++;
	}

}
